package com.yxj.lib_exo;

import static com.yxj.lib_exo.ExoPlayerView.showLog;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.SeekBar;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;

public class ExoPlayerControl extends FrameLayout implements ExoPlayListener {

    private View view;
    //创建播放器实例
    private ExoPlayer player;

    public ExoPlayerClick exoPlayerClick = new ExoPlayerClick();


    public void setPlayer(ExoPlayer player) {
        this.player = player;
        player.addListener(new Player.Listener() {

            @Override
            public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                showLog("STATE_READY");
                onProgress(player.getDuration(), player.getCurrentPosition());
                onPlayTime(ExoVideoTimeUtil.formatTime(player.getDuration()), ExoVideoTimeUtil.formatTime(player.getCurrentPosition()));
            }

            @Override
            public void onIsLoadingChanged(boolean isLoading) {
                Player.Listener.super.onIsLoadingChanged(isLoading);
                showLog("STATE_BUFFERING isLoading = " + isLoading);
                onLoading(isLoading);
            }


            @Override
            public void onPlayerError(PlaybackException error) {
                Player.Listener.super.onPlayerError(error);
            }

            @Override
            public void onIsPlayingChanged(boolean isPlaying) {
                Player.Listener.super.onIsPlayingChanged(isPlaying);
                showLog("STATE_READY isPlaying = " + isPlaying);
                if (isPlaying) {
                    handler.postDelayed(updateProgressAction, 0);
                } else {
                    handler.removeCallbacks(updateProgressAction, 0);
                }
                onPlayingChanged(isPlaying);
            }


            @Override
            public void onPlaybackStateChanged(int playbackState) {
                switch (playbackState) {
                    case Player.STATE_IDLE:
                        showLog("STATE_IDLE");
                        break;

                    case Player.STATE_BUFFERING:
                        showLog("STATE_BUFFERING");
                        onLoading(true);
                        break;

                    case Player.STATE_READY:
                        showLog("STATE_READY Duration = " + player.getDuration());
                        break;

                    case Player.STATE_ENDED:
                        onPlayEnd();
                        showLog("STATE_ENDED");
                        player.pause();
                        player.seekTo(0); // 回到视频开头
                        break;
                }
            }
        });
    }

    public ExoPlayerControl(@NonNull Context context) {
        this(context, null);
    }

    public ExoPlayerControl(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ExoPlayerControl(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        addView(view = LayoutInflater.from(getContext()).inflate(R.layout.play_control_layout, this, false));
        exoPlayerClick.setExoClickListener(new ExoOnClickListener() {
            @Override
            public void onClick() {
                if (player.isPlaying()) {
                    player.pause();
                } else {
                    player.play();
                }
            }
        });
        dragSeekBar();
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        exoPlayerClick.onTouchEvent(event);
        return true;
    }


    /**
     * 加载中
     *
     * @param isLoading
     */
    public void loading(boolean isLoading) {
//        ProgressBar imLoading = view.findViewById(R.id.imLoading);
//        imLoading.setIndeterminateDrawable(getResources().getDrawable(R.drawable.loading));
//        imLoading.setVisibility(isLoading ? View.VISIBLE : GONE);
//        ((HorizontalLoadingView)view.findViewById(R.id.mHorizontalLoadingView)).loading(isLoading);
    }


    public void showPlayView(boolean b) {
        view.findViewById(R.id.btnPlayPause).setVisibility(b ? View.VISIBLE : GONE);
    }


    @Override
    public void onLoading(boolean b) {
        loading(b);
    }


    @Override
    public void onProgress(long total, long currentProgress) {
        showProgress((int) (currentProgress * 1.0f / total * 10000));
    }


    @Override
    public void onPlayingChanged(boolean isPlaying) {
        showPlayView(!isPlaying);
    }


    @Override
    public void onPlayTime(String totalTime, String currentTime) {
        showTime(totalTime, currentTime);
    }


    @Override
    public void onPlayEnd() {

    }


    /**
     * 点击事件
     */
    public interface ExoClickListener {
        /**
         * 点击事件
         */
        void onClick();

        /**
         * 长按事件
         */
        void onLongClick();
    }


    public static class ExoOnClickListener implements ExoClickListener {

        @Override
        public void onClick() {

        }

        @Override
        public void onLongClick() {

        }
    }


    /**
     * @param progress
     */
    public void showProgress(int progress) {
        ((SeekBar) view.findViewById(R.id.progress_bar)).setProgress(progress);
    }


    /**
     * 显示时间
     *
     * @param totalTime
     * @param currentTime
     */
    public void showTime(String totalTime, String currentTime) {
        ((TextView) view.findViewById(R.id.tvCurrentTime)).setText(currentTime);
        ((TextView) view.findViewById(R.id.tvTotalTime)).setText(totalTime);
    }


    public void removeCallbacks() {
        handler.removeCallbacks(updateProgressAction, 0);
    }

    private Handler handler = new Handler(Looper.getMainLooper());
    private Runnable updateProgressAction = new Runnable() {
        @Override
        public void run() {
            if (player != null && player.isPlaying()) {
                // 获取当前播放位置和总时长
                long position = player.getCurrentPosition();
                long duration = player.getDuration();

                //当前时间
                String currentTime = ExoVideoTimeUtil.formatTime(position);
                //总时长
                String totalTime = ExoVideoTimeUtil.formatTime(duration);

                showLog(new StringBuilder()
                        .append("length=" + duration)
                        .append("   ")
                        .append("position = " + position)
                        .append("   ")
                        .append("currentTime = " + currentTime)
                        .append("   ")
                        .append("totalTime = " + totalTime)
                        .toString());

                onProgress(duration, position);
                onPlayTime(totalTime, currentTime);
            }
            // 每200ms更新一次
            handler.postDelayed(this, 5);
        }
    };


    /**
     * 控制栏样式
     *
     * @param seekBarStyle
     */
    public void setSeekBarStyle(SeekBarStyle seekBarStyle) {
        switch (seekBarStyle) {
            case NONE:
                showSeekBarStyle3();
                break;
            case PROGRESS:
                showSeekBarStyle2();
                break;
            case TIME_PROGRESS:
                showSeekBarStyle1();
                break;
        }
    }


    public enum SeekBarStyle {
        //只有视频
        NONE,
        //视频时间和进度
        TIME_PROGRESS,
        //只有进度
        PROGRESS
    }


    private void showSeekBarStyle3() {
        view.findViewById(R.id.layBottomControl).setVisibility(GONE);
    }


    private void showSeekBarStyle1() {
        view.findViewById(R.id.layBottomControl).setVisibility(VISIBLE);
        (view.findViewById(R.id.tvCurrentTime)).setVisibility(VISIBLE);
        (view.findViewById(R.id.tvTotalTime)).setVisibility(VISIBLE);
        (view.findViewById(R.id.layProgressBar)).setVisibility(VISIBLE);
    }


    private void showSeekBarStyle2() {
        view.findViewById(R.id.layBottomControl).setVisibility(VISIBLE);
        (view.findViewById(R.id.tvCurrentTime)).setVisibility(GONE);
        (view.findViewById(R.id.tvTotalTime)).setVisibility(GONE);
        (view.findViewById(R.id.layProgressBar)).setVisibility(VISIBLE);
        SeekBar progress_bar = view.findViewById(R.id.progress_bar);
        progress_bar.setThumb(getResources().getDrawable(R.drawable.custom_thumb));
        progress_bar.setProgressDrawable(getResources().getDrawable(R.drawable.custom_progress_bar));
        ViewGroup.LayoutParams d = progress_bar.getLayoutParams();
        d.height = 4 ;
        progress_bar.setLayoutParams(d);
        seekBarSize();
    }





    /**
     * 处理seekBar 因为两边的间距不能完全填充满的问题
     */
    public void seekBarSize() {
        getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (getWidth() != 0) {
                    int w = getMeasuredWidth();
                    View progress_bar = view.findViewById(R.id.progress_bar);
                    float px = (getResources().getDisplayMetrics().density * 40 + 0.5f);
                    float f = px / w + 1;
                    progress_bar.setScaleX(f);
                    getViewTreeObserver().removeOnGlobalLayoutListener(this::onGlobalLayout);
                }
            }
        });
    }


    boolean isDrag = false;
    public void dragSeekBar() {
        SeekBar progress_bar = view.findViewById(R.id.progress_bar);
        progress_bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (isDrag && player != null) {
                    float f = seekBar.getProgress() * 1.0f / seekBar.getMax();
                    long duration = player.getDuration();
                    if (duration > 0) {
                        player.seekTo((long) (duration * f));
                    }
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                if (player != null && player.isPlaying()) {
                    isDrag = true;
                    player.pause();
                }
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                if (player != null) {
                    player.play();
                }
                isDrag = false;
            }
        });
    }
}
